package com.authine.cloudpivot.ext.service.impl;

import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.ext.applicationservice.base.ApplicationBaseService;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.ServiceUrlConst;
import com.authine.cloudpivot.ext.dto.OrderCustomerGoodsDto;
import com.authine.cloudpivot.ext.dto.api.BulkRefundVO;
import com.authine.cloudpivot.ext.dto.finance.TradeErpPoUpdate;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.enums.order.GoodsSrcEnum;
import com.authine.cloudpivot.ext.service.DockFinanceService;
import com.authine.cloudpivot.ext.service.OrderService;
import com.authine.cloudpivot.ext.utils.HttpClients;
import com.authine.cloudpivot.ext.utils.JdbcTemplateUtils;
import com.authine.cloudpivot.ext.utils.StringUtils;
import com.authine.cloudpivot.ext.utils.TypeReferenceUtils;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.DateUtils;
import com.authine.mvp.app.launcher.utils.JsonParseObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 对接财务接口方法实现类
 */
@Slf4j
public class DockFinanceServiceImpl extends ApplicationBaseService implements DockFinanceService {

    private final static OrderService orderService = new OrderServiceImpl();

    /**
     * 调用财务生成交易记录
     *
     * @param orderCustomerIds 客户订单ID
     * @return
     */
    @Override
    public SingleResponse createTrade(Collection<String> orderCustomerIds) {
        List<Map<String, Object>> orderCustomerGoods = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER_GOODS)
                .selectField("*").in("order_customer_id", orderCustomerIds).queryForList();
        log.info("调用财务生成交易记录 查询结果:" + JSON.toJSONString(orderCustomerGoods));
        if (CollectionUtils.isEmpty(orderCustomerGoods)) {
            return null;
        }
        String res = null;
        List<Map<String, Object>> orderGoodsConvertTrades = new ArrayList<>();
        for (Map<String, Object> orderCustomerGood : orderCustomerGoods) {
            Map<String, Object> orderGoodsConvertTrade = new HashMap<>();
            List<SelectorFormat> customer_organization_ids = Objects.isNull(orderCustomerGood.get("customer_organization_id")) ? null : JsonParseObject.parseObject((String) orderCustomerGood.get("customer_organization_id"), SelectorFormat.class);
            List<SelectorFormat> vendor_organization_ids = Objects.isNull(orderCustomerGood.get("vendor_organization_id")) ? null : JsonParseObject.parseObject((String) orderCustomerGood.get("vendor_organization_id"), SelectorFormat.class);
            orderGoodsConvertTrade.put("erpPo", orderCustomerGood.get("erp_po"));
            orderGoodsConvertTrade.put("sku", orderCustomerGood.get("sku"));
            orderGoodsConvertTrade.put("businessType", orderCustomerGood.get("goods_src").equals(GoodsSrcEnum.Contract.name()) ? "Agent" : "Ordinary");
            orderGoodsConvertTrade.put("customerOrganizationId", getTransactionOrganizationId(customer_organization_ids));
            orderGoodsConvertTrade.put("vendorOrganizationId", getTransactionOrganizationId(vendor_organization_ids));
            List<SelectorFormat> place_order_user_ids = Objects.isNull(orderCustomerGood.get("place_order_user_id")) ? null : JsonParseObject.parseObject((String) orderCustomerGood.get("place_order_user_id"), SelectorFormat.class);
            orderGoodsConvertTrade.put("memberId", CollectionUtils.isEmpty(place_order_user_ids) ? null : place_order_user_ids.get(0).getId());
            orderGoodsConvertTrade.put("memberName", CollectionUtils.isEmpty(place_order_user_ids) ? null : place_order_user_ids.get(0).getName());
            orderGoodsConvertTrade.put("customerOrderGoodsId", orderCustomerGood.get("id"));
            Map<String, Object> orderVendorGoods = orderService.getOrderGoods((String) orderCustomerGood.get("id"), null);
            orderGoodsConvertTrade.put("vendorOrderGoodsId", CollectionUtils.isEmpty(orderVendorGoods) ? null : orderVendorGoods.get("id"));
            orderGoodsConvertTrade.put("price", orderCustomerGood.get("price"));
            orderGoodsConvertTrade.put("pretax_price", orderCustomerGood.get("pretax_price"));
            //商品未税金额
            orderGoodsConvertTrade.put("total_before_tax", orderCustomerGood.get("pretax_total"));
            //总未税金额
            orderGoodsConvertTrade.put("amount_before_tax", orderCustomerGood.get("pretax_amount"));
            Map<String, Object> orderCustomer = JdbcTemplateUtils.builder(ModelConst.T_ORDER_CUSTOMER).selectField("*").eq("id", orderCustomerGood.get("order_customer_id")).queryForMap();
            //订单收货人
            orderGoodsConvertTrade.put("order_receiver", orderCustomer.get("receiver"));
            //订单收货地址
            orderGoodsConvertTrade.put("order_address", orderCustomer.get("address"));
            orderGoodsConvertTrade.put("quantity", orderCustomerGood.get("quantity"));
            orderGoodsConvertTrade.put("taxRate", orderCustomerGood.get("tax_rate"));
            orderGoodsConvertTrade.put("accountPeriod", orderCustomerGood.get("customer_account_period"));
            Map<String, Object> summary = new HashMap<>();
            summary.put("name", orderCustomerGood.get("name"));
            summary.put("brand", orderCustomerGood.get("brand"));
            summary.put("spec", orderCustomerGood.get("spec"));
            summary.put("model", orderCustomerGood.get("model"));
            summary.put("unit", orderCustomerGood.get("unit"));
            orderGoodsConvertTrade.put("summary", summary);
            orderGoodsConvertTrade.put("unit", orderCustomerGood.get("unit"));
            orderGoodsConvertTrade.put("vendorOrderId", orderCustomerGood.get("order_vendor_id"));
            orderGoodsConvertTrade.put("customerOrderId", orderCustomerGood.get("order_customer_id"));
            orderGoodsConvertTrade.put("freight", orderCustomerGood.get("freight"));
            orderGoodsConvertTrade.put("goldenTax", orderCustomerGood.get("golden_tax"));
            orderGoodsConvertTrade.put("orderGoodsStatus", orderCustomerGood.get("order_customer_goods_status"));
            orderGoodsConvertTrade.put("amount", orderCustomerGood.get("amount"));
            orderGoodsConvertTrade.put("total", orderCustomerGood.get("total"));
            Map<String, Object> transferPurchase = JdbcTemplateUtils.builder(ModelConst.T_TRANSFER_ORDER_GOODS).selectField("*")
                    .eq("cloudOrderGoodsId", orderCustomerGood.get("id")).queryForMap();
            orderGoodsConvertTrade.put("transferPurchase", CollectionUtils.isEmpty(transferPurchase) ? false : true);
            orderGoodsConvertTrade.put("description", orderCustomerGood.get("description"));
            //获取订单商品关联表数据
            Map<String, Object> orderGoodsRelation = JdbcTemplateUtils.builder(ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                    .eq("id", orderCustomerGood.get("relation_id")).queryForMap();
            Map<String, Object> tradeExtendsAttr = new HashMap<>();
            //对接外部工厂代码
            tradeExtendsAttr.put("clientFactoryCode", CollectionUtils.isEmpty(orderGoodsRelation) ? null : orderGoodsRelation.get("client_factory_code"));
            orderGoodsConvertTrade.put("extendsAttr", tradeExtendsAttr);

            orderGoodsConvertTrade.put("erpPoLineNumber", orderCustomerGood.get("erp_po_line_number"));
            Map<String, Object> inquiry = this.getInquiry((String) orderCustomerGood.get("relation_id"));
            orderGoodsConvertTrade.put("inquiryTime", CollectionUtils.isEmpty(inquiry) ? null : DateUtils.getDate((Date) inquiry.get("createdTime"), "yyyy-MM-dd HH:mm:ss"));
            orderGoodsConvertTrades.add(orderGoodsConvertTrade);
        }
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.CREATE_TRADE_URL);
        log.info("调用财务生成交易记录参数param:" + JSON.toJSONString(orderGoodsConvertTrades));
        res = HttpClients.execute(url, orderGoodsConvertTrades);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(res);
        log.info("调用财务生成交易记录参数结果：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 回写交易对应的ERP_PO号
     *
     * @param tradeErpPoUpdates
     */
    @Override
    public SingleResponse writeBackErpPo(List<TradeErpPoUpdate> tradeErpPoUpdates) {
        if (CollectionUtils.isEmpty(tradeErpPoUpdates)) {
            return SingleResponse.buildFailure("-1", "回写交易对应的ERP_PO号入参为空");
        }
        List<Map<String, Object>> writeBackParams = new ArrayList<>();
        for (TradeErpPoUpdate tradeErpPoUpdate : tradeErpPoUpdates) {
            if (StringUtils.isBlank(tradeErpPoUpdate.getCustomerOrderId()) || StringUtils.isBlank(tradeErpPoUpdate.getErpPo())) {
                return SingleResponse.buildFailure("-1", "回写交易对应的ERP_PO号入参为空");
            }
            Map<String, Object> writeBackParam = new HashMap<>();
            writeBackParam.put("customerOrderId", tradeErpPoUpdate.getCustomerOrderId());
            writeBackParam.put("erpPo", tradeErpPoUpdate.getErpPo());
            writeBackParams.add(writeBackParam);
        }
        //回写交易对应的ERP_PO号
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.WRITE_BACK_ERP_PO_URL);
        log.info("回写交易对应的ERP_PO号 param:" + JSON.toJSONString(writeBackParams));
        String result = HttpClients.execute(url, writeBackParams);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(result);
        log.info("回写交易对应的ERP_PO号结果：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 回写订单对应交易的订单商品状态
     */
    @Override
    public SingleResponse writeBackTradesOrder(List<Map<String, Object>> writeBackParams) {
        log.info("回写订单对应交易的订单商品状态 param:" + JSON.toJSONString(writeBackParams));
        if (CollectionUtils.isEmpty(writeBackParams)) {
            return SingleResponse.buildFailure("-1", "回写订单对应交易的订单商品状态入参为空");
        }
        //回写商品状态
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.WRITE_BACK_TRADES_ORDER_URL);
        String result = HttpClients.execute(url, writeBackParams);
        log.info("回写订单对应交易的订单商品状态 result:" + result);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(result);
        log.info("回写订单对应交易的订单商品状态结果：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 回写对应交易的金税编码
     */
    @Override
    public SingleResponse writeBackTradesOrder(OrderCustomerGoodsDto dto) {
        if (StringUtils.isBlank(dto.getId()) || StringUtils.isBlank(dto.getGoldenTax())) {
            return SingleResponse.buildFailure("-1", "回写对应交易的金税编码入参为空");
        }
        Map<String, Object> writeBackParam = new HashMap<>();
        writeBackParam.put("orderGoodsId", dto.getId());
        writeBackParam.put("goldenTax", dto.getGoldenTax());
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.WRITE_BACK_GOLDEN_TAX_URL);
        log.info("回写对应交易的金税编码 param:" + JSON.toJSONString(writeBackParam));
        String result = HttpClients.execute(url, Collections.singletonList(writeBackParam));
        log.info("回写对应交易的金税编码 result:" + result);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(result);
        log.info("回写对应交易的金税编码结果：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 创建退货账单
     */
    @Override
    public SingleResponse refundBill(List<Map<String, Object>> bulkRefundVOs) {
        if (CollectionUtils.isEmpty(bulkRefundVOs)) {
            return SingleResponse.buildFailure("-1", "创建退货账单入参为空");
        }
        List<Map<String, Object>> orderGoodsParam = new ArrayList<>();
        bulkRefundVOs.forEach(bulkRefundMap ->{
            Map<String, Object> orderGoodMap = new HashMap<>();
            orderGoodMap.put("quantity", bulkRefundMap.get("quantity"));
            orderGoodMap.put("type","Refund");
            //是否要退货  true=需要收货，false=仅退款不需要退货
            orderGoodMap.put("refundNonExist",bulkRefundMap.get("is_returns"));
            orderGoodMap.put("order_goods_id", bulkRefundMap.get("order_customer_goods_id"));
            orderGoodMap.put("direction", "Sale");
            //是否退平台
            Boolean isToPm = Boolean.parseBoolean(bulkRefundMap.get("is_to_pm").toString());
            if (isToPm){
                orderGoodMap.put("order_goods_id", bulkRefundMap.get("order_vendor_goods_id"));
                orderGoodMap.put("direction", "Purchase");
            }
            //退款类型
            orderGoodsParam.add(orderGoodMap);
        });
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.REFUND_BILL_URL);
        log.info("创建退货账单 param:" + JSON.toJSONString(orderGoodsParam));
        String result = HttpClients.execute(url, orderGoodsParam);
        log.info("创建退货账单 result:" + result);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(result);
        log.info("创建退货账单结果：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 确认收货生成商品账单
     */
    @Override
    public SingleResponse createBill(List<Map<String, Object>> orderGoods) {
        if (CollectionUtils.isEmpty(orderGoods)) {
            return SingleResponse.buildFailure("-1", "确认收货生成商品账单入参为空");
        }
        List<Map<String, Object>> orderGoodsParam = new ArrayList<>();
        for (Map<String, Object> orderGood : orderGoods) {
            Map<String, Object> orderGoodMap = new HashMap<>();
            orderGoodMap.put("order_goods_id", orderGood.get("id"));
            orderGoodMap.put("direction", "Sale");
            orderGoodMap.put("business_type", orderGood.get("goods_src").equals(GoodsSrcEnum.Contract.name()) ? "Agent" : "Ordinary");
            orderGoodMap.put("quantity", orderGood.get("num"));
            orderGoodMap.put("type", "Goods");
            orderGoodsParam.add(orderGoodMap);

            Map<String, Object> orderVendorGoods = orderService.getOrderGoods((String) orderGood.get("id"), null);

            Map<String, Object> orderVendorGoodsMap = new HashMap<>();
            orderVendorGoodsMap.put("order_goods_id", orderVendorGoods.get("id"));
            orderVendorGoodsMap.put("direction", "Purchase");
            orderVendorGoodsMap.put("business_type", orderGood.get("goods_src").equals(GoodsSrcEnum.Contract.name()) ? "Agent" : "Ordinary");
            orderVendorGoodsMap.put("quantity", orderGood.get("num"));
            orderVendorGoodsMap.put("type", "Goods");
            orderGoodsParam.add(orderVendorGoodsMap);
        }
        Map bill = new HashMap();
        bill.put("bills", orderGoodsParam);
        String url = HttpClients.getUrl(AppConst.FINANCIALCENTER, ServiceUrlConst.CREATE_BILL_URL);
        log.info("确认收货生成商品账单 param:" + JSON.toJSONString(bill));
        String result = HttpClients.execute(url, bill);
        log.info("确认收货生成商品账单 result:" + result);
        SingleResponse response = TypeReferenceUtils.readValueToSingleRes(result);
        log.info("确认收货生成商品账单：" + JSON.toJSONString(response));
        if(!response.isSuccess()){
            throw new RuntimeException(response.getErrMessage());
        }
        return response;
    }

    /**
     * 获得结算组织
     * @return
     */
    private SelectorFormat getTransactionOrganizationId(List<SelectorFormat> organizationIds){

        OrganizationDto organization = Optional.ofNullable(OrgUtils.getOrgByOrgId(CollectionUtils.isEmpty(organizationIds) ? null :
                organizationIds.get(0).getId())).orElseThrow(() -> new BizException("用户组织不可用!"));
        if (null == organization) throw new BizException("结算组织账户不能为空，请联系管理员添加结算组织账户!");
        if (null == organization.getTransaction_organization_id()) throw new BizException("结算组织账户不能为空，请联系管理员添加结算组织账户!");
        SelectorFormat tranOrgId = organization.getTransaction_organization_id().get(0);
        if (null == tranOrgId) throw new BizException("结算组织账户不能为空，请联系管理员添加结算组织账户!");
        return tranOrgId;
    }
}
